home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / Anwendun / a2html / a2html-0.81 / source / a2html.c next >
Encoding:
C/C++ Source or Header  |  1999-08-28  |  51.4 KB  |  1,508 lines

  1. /* 
  2.  * $Id: a2html.c,v 1.8 1999/08/28 19:20:35 tommya Exp $
  3.  *
  4.  * Ascii to html
  5.  *
  6.  *  Search "show_help" for usage.
  7.  *  Tab not used.
  8.  *
  9.  * THIS PROGRAM IS PUBLIC DOMAIN (NO COPYRIGHT)
  10.  *
  11.  * see changes list of changes.
  12.  *
  13.  * Created by Tommy Andersen 1997,98,99
  14.  * Compiler: Lattice C (Atari) + GCC (Atari or Linux)
  15.  */
  16.  
  17.  
  18. #ifdef ATARI
  19. #include <mintbind.h>
  20. #include <osbind.h>
  21. #endif
  22. #include <strings.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <unistd.h>
  26.  
  27. #ifdef ATARI
  28. #define MC " Atari"
  29. #else
  30. #define MC " Linux"
  31. #endif
  32.  
  33. #ifdef __MINT__
  34. #define LV " Mintlib"
  35. #else
  36. #define LV
  37. #endif
  38.  
  39. #define VERSION "0.81" MC LV
  40. #define WORD_LENGTH 1000
  41. #define HTML_EXTENSION ".html"
  42. #define RC_LINE_BUFFER 1000
  43. #define MAX_VAR_LENGTH 50
  44.  
  45. /* Control these <br> a2html invents  */
  46. #define DISALLOW_BR 0
  47. #define ALLOW_BR 1
  48. #define FORCE_BR 2
  49.  
  50. #if defined(LATTICE) && !defined(__LATTICE__)
  51. /* Not using mintlib with Lattice?  */
  52. #define strncasecmp strnicmp
  53. #endif
  54.  
  55. const unsigned char header_doctype[] =
  56.   "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n";
  57.  
  58. const unsigned char header_tags1[] =
  59.   "<html>\n" \
  60.   "<head>\n" \
  61.   "<title>";
  62.  
  63. const unsigned char header_tags2[] =
  64.   "</title>\n" \
  65.   "</head>\n" \
  66.   "<!-- Created with a2html "VERSION" -->\n";
  67.  
  68. const unsigned char pre_start_tag[] = "<pre>\n";
  69. const unsigned char pre_end_tag[]   = "</pre>\n";
  70.  
  71. const unsigned char bottom_tags[] =
  72.   "</body>\n" \
  73.   "</html>\n";
  74.  
  75. const unsigned char * const url_types[] =
  76.   { "ftp", "http", "file", "news", "wais", "nntp", "imap", "https", \
  77.     "telnet", "mailto", "gopher", "prospero", NULL
  78.   };
  79.  
  80. /* If input file is a email, these header lines are displayed  */
  81.  
  82. const unsigned char * const show_emh_field[] =
  83.   {  "date", "from", "reply-to", "to", "cc", "subject", NULL };
  84.  
  85. char *yes_strings[] = { "1", "yes", "true", "sure", NULL };
  86. char *no_strings[] = { "0", "no", "false", "noway", NULL };
  87.  
  88. /*
  89.  * Atari charset to iso8859-1 charset
  90.  * Just a simple lookup array
  91.  * The Atari char is used as an index, the lookup value is the iso8859-1 char.
  92.  */
  93.  
  94. const unsigned char convertAtariToIso88591[]=
  95.   { /*  0-9  */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  96.     /* 10-19 */ 10, ' ', ' ', 13, ' ', ' ', ' ', ' ', ' ', ' ',
  97.     /* 20-29 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  98.     /* 30-39 */ ' ', ' ', ' ', '!',  34, '#', '$', '%', '&', 39,
  99.     /* 40-49 */ '(', ')', '*', '+', ',', '-', '.', '/', '0', '1',
  100.     /* 50-59 */ '2', '3', '4', '5', '6', '7', '8', '9', ':', ';',
  101.     /* 60-69 */ '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E',
  102.     /* 70-79 */ 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  103.     /* 80-89 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
  104.     /* 90-99 */ 'Z', '[', 92 , ']', '^', '_', '`', 'a', 'b', 'c',
  105.     /*100-109*/ 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  106.     /*110-119*/ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
  107.     /*120-129*/ 'x', 'y', 'z', '{', '|', '}', '~', ' ', 199, 252,
  108.     /*130-139*/ 233, 226, 228, 224, 229, 231, 234, 235, 232, 239,
  109.     /*140-149*/ 238, 236, 196, 197, 201, 230, 198, 244, 246, 242,
  110.     /*150-159*/ 251, 249, 255, 214, 220, 162, 163, 165, 223, ' ',
  111.     /*160-169*/ 225, 237, 243, 250, 241, 209, ' ', ' ', 191, ' ',
  112.     /*170-179*/ 172, 189, 188, 161, 171, 187, 227, 245, 216, 248,
  113.     /*180-189*/ 230, 198, 192, 195, 213, 168, 180, ' ', 182, 169,
  114.     /*190-199*/ 174, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  115.     /*200-209*/ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  116.     /*210-219*/ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  117.     /*220-229*/ ' ', 167, ' ', ' ', ' ', 223, ' ', ' ', ' ', ' ',
  118.     /*230-239*/ 181, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  119.     /*240-249*/ ' ', 177, ' ', ' ', ' ', ' ', 247, ' ', 176, ' ',
  120.     /*250-255*/ 183, ' ', ' ', 178, 179, 175
  121.   };
  122.  
  123. /* 8 bit iso-8859-1 to 7bit html */
  124. /* lookup string table */
  125.  
  126. /* " = "    =   */
  127.  
  128. const unsigned char * const convertIso88591ToHtml[]=
  129.   { /*  0-9  */ " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  130.     /* 10-19 */ "\n", " ", " ", NULL, " ", " ", " ", " ", " ", " ",
  131.     /* 20-29 */ " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  132.     /* 30-39 */ " ", " ", " ", "!", ""","#", "$", "%", "&", "'",
  133.     /* 40-49 */ "(", ")", "*", "+", ",", "-", ".", "/", "0", "1",
  134.     /* 50-59 */ "2", "3", "4", "5", "6", "7", "8", "9", ":", ";",
  135.     /* 60-69 */ "<", "=", ">", "?", "@", "A", "B", "C", "D", "E",
  136.     /* 70-79 */ "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
  137.     /* 80-89 */ "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
  138.     /* 90-99 */ "Z", "[", "\\","]", "^", "_", "`", "a", "b", "c",
  139.     /*100-109*/ "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
  140.     /*110-119*/ "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
  141.     /*120-129*/ "x", "y", "z", "{", "|", "}", "~", " ", " ", " ", /* 128-159 not used */
  142.     /*130-139*/ " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  143.     /*140-149*/ " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  144.     /*150-159*/ " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  145.     /*160-169*/ " ","¡","¢","£","¤","¥","¦","§","¨","©",
  146.     /*170-179*/ "ª","«","¬","­","®","¯","°","±","²","³",
  147.     /*180-189*/ "´","µ","¶","·","¸","¹","º","»","¼","½",
  148.     /*190-199*/ "¾","¿","À","Á","Â","Ã","Ä","Å","Æ","Ç",
  149.     /*200-209*/ "È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ",
  150.     /*210-219*/ "Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û",
  151.     /*220-229*/ "Ü","Ý","Þ","ß","à","á","â","ã","ä","å",
  152.     /*230-239*/ "æ", "ç","è","é","ê","ë","ì","í","î","ï",
  153.     /*240-249*/ "ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù",
  154.     /*250-255*/ "ú","û","ü","ý","þ", "ÿ"
  155.   };
  156.  
  157. struct file_entry
  158.   { char *input_filename;    /* file to convert  */
  159.     char *output_filename;  /* where to put the output  */
  160.     unsigned char *title_html;
  161.     struct file_entry *next;
  162.   } *work_list = NULL;
  163.  
  164. struct emh_text_entry
  165.   {
  166.     struct emh_text_entry *next;
  167.     unsigned char *text;
  168.   };
  169.  
  170.  
  171.  
  172. /*
  173.  *   Prototypes
  174.  */
  175.  
  176. int main (int argc, char *[]);
  177. void output_error_text (char *);
  178. int make_html_file (char *, char*, const unsigned char*);
  179. void make_output_filename (const char *, char *, const char*);
  180. struct file_entry *create_entry (void);
  181. void free_list (struct file_entry *);
  182. void show_help (int);
  183. void output_char (const int, int, FILE *);
  184. void output_string (const int, const char *, FILE *);
  185. void output_parse_char (const int, unsigned int, FILE *);
  186. void output_parse_string (const int, const char *, FILE *);
  187. void output_word (const int, const unsigned char *word, FILE *handle);
  188. char *find_filename (char *);
  189. void read_rc_file (char *);
  190. void set_var (char *variable, char *value);
  191. FILE *fopen_rc_file (const char *rc_name, const char *mode);
  192.  
  193. /*
  194.  *   Some default settings
  195.  */
  196.  
  197. #define ATARICHARSET 0
  198. #define ISOCHARSET   1
  199. #define TRUE 1
  200. #define FALSE 0
  201. #define NA -1
  202.  
  203. #ifdef ATARI
  204. int method = ATARICHARSET;   /* input files uses the Atari charset  */
  205. #else
  206. int method = ISOCHARSET;     /* input files uses the ISO-8859-1 charset  */
  207. #endif
  208. int quiet = FALSE;           /* print errors to stderr  */
  209. int pause_required = FALSE;           /* don't wait for a keypress  */
  210. int crlf = FALSE;            /* use un*x lines  */
  211. int notags = FALSE;          /* use tags in output  */
  212. int nopre = FALSE;           /* use <pre> tags  */
  213. int nolinks = FALSE;         /* check for links  */
  214. int nomail = FALSE;          /* check for emailadress */
  215. int nobr = FALSE;            /* use <br> if <nopre> is true  */
  216. int doctype = TRUE;          /* output html doctype  */
  217. int emailsource = FALSE;     /* Input file is a normal ascii file  */
  218. unsigned char *footer_html = NULL; /* footer text - raw html code  */
  219. unsigned char *separator_html = NULL;  /* Emailer separator - raw html code  */
  220. char *bodybgcolor = NULL;
  221. char *bodytext = NULL;
  222. char *bodylink = NULL;
  223.  
  224.  
  225.  
  226. #define ARGUMENT_IS(x) (!strcmp ((x), argv[a]))
  227. #undef max
  228. #define max(x,y) ((x) > (y) ? (x) : (y))
  229.  
  230. int
  231. main (int argc, char *argv[])
  232. {
  233.   int a = 1;
  234.   int ret = 0;
  235.   int save_argc = argc;
  236.  
  237.   struct file_entry *current, *prev;
  238.  
  239. #ifdef ATARI
  240.  #if defined(LATTICE) && !defined(__LATTICE__)
  241.   Pdomain (1);      /* mint domain, gcc (MiNT) doesn't need it  */
  242.   fmode (stdout,1);  /* binary output -- no translation VERY IMPORTANT!  */
  243.  #else
  244.   stdout->_flag |= _IOBIN;  /* force binary output (mintlib)  */
  245.  #endif
  246. #endif
  247.  
  248.   read_rc_file ("a2htmlrc");
  249.  
  250.   current = work_list = create_entry ();
  251.  
  252.   if (!current)
  253.     exit (1);  /* low memory! Shouldn't be possible  */
  254.  
  255.  
  256.   /* parse command line and build a list of files */
  257.   while (--argc > 0)
  258.     {
  259.       if (ARGUMENT_IS ("-iso") || ARGUMENT_IS("-iso-8859-1"))
  260.         method = ISOCHARSET;
  261.       else if (ARGUMENT_IS ("-atari"))
  262.         method = ATARICHARSET;
  263.       else if (ARGUMENT_IS ("-q") || ARGUMENT_IS ("-quiet"))
  264.         quiet = TRUE;
  265.       else if (ARGUMENT_IS ("-p") || ARGUMENT_IS ("-pause"))
  266.         pause_required = TRUE;
  267.       else if (ARGUMENT_IS ("-crlf"))
  268.         crlf = TRUE;
  269.       else if (ARGUMENT_IS ("-notags"))
  270.         notags = TRUE;
  271.       else if (ARGUMENT_IS ("-nolinks"))
  272.         nolinks = TRUE;
  273.       else if (ARGUMENT_IS ("-nomail"))
  274.         nomail = TRUE;
  275.       else if (ARGUMENT_IS ("-nopre"))
  276.         nopre = TRUE;
  277.       else if (ARGUMENT_IS ("-nobr"))
  278.         nobr = TRUE;
  279.       else if (ARGUMENT_IS ("-nodoctype"))
  280.         doctype = FALSE;
  281.       else if (ARGUMENT_IS ("-emailsource"))
  282.         {
  283.           emailsource = TRUE;
  284.           method = ISOCHARSET;  /* forced  */
  285.         }
  286.       else if (ARGUMENT_IS ("--help"))
  287.         {
  288.           show_help (TRUE);
  289.           if (pause_required)
  290.             {
  291.               output_error_text ("\nPress Return\n");
  292.               getchar ();
  293.             }
  294.           exit (1);
  295.         }
  296.       else if (ARGUMENT_IS ("--version"))
  297.         {
  298.           show_help (FALSE);
  299.           if (pause_required)
  300.             {
  301.               output_error_text ("\nPress Return\n");
  302.               getchar ();
  303.             }
  304.           exit (1);
  305.         }
  306.       else if (ARGUMENT_IS ("-dumpargs"))
  307.         {
  308.           int a=0;
  309.           char *some_text = (char*) malloc (2000);
  310.  
  311.           while (save_argc-- && some_text)
  312.             {
  313.               sprintf (some_text, "Arg no. %d is (%s)\n", a, argv[a] ? argv[a] : "nothing");
  314.               output_error_text (some_text);
  315.               a++;
  316.             }
  317.           if (some_text)
  318.             free (some_text);
  319.         }
  320.       else if (ARGUMENT_IS ("-footer")) /* footer text specified  */
  321.         {
  322.           a++;
  323.           if (--argc > 0)  /* must have an extra argument  */
  324.             {
  325.               if (footer_html)
  326.                 free (footer_html);
  327.               footer_html = (char*) strdup (argv[a]);
  328.             }
  329.         }
  330.       else if (ARGUMENT_IS ("-separator")) /* separator text specified  */
  331.         {
  332.           a++;
  333.           if (--argc > 0)  /* must have an extra argument  */
  334.             {
  335.               if (separator_html)
  336.                 free (separator_html);
  337.               separator_html = (char*) strdup (argv[a]);
  338.             }
  339.         }
  340.       else if (ARGUMENT_IS ("-bodybgcolor")) /* body background color specified  */
  341.         {
  342.           a++;
  343.           if (--argc > 0)
  344.             {
  345.               if (bodybgcolor)
  346.                 free (bodybgcolor);
  347.               bodybgcolor = (char*) strdup (argv[a]);
  348.             }
  349.         }
  350.       else if (ARGUMENT_IS ("-bodytext")) /* body text color specified  */
  351.         {
  352.           a++;
  353.           if (--argc > 0)
  354.             {
  355.               if (bodytext)
  356.                 free (bodytext);
  357.               bodytext = (char*) strdup (argv[a]);
  358.             }
  359.         }
  360.       else if (ARGUMENT_IS ("-bodylink")) /* body link color specified  */
  361.         {
  362.           a++;
  363.           if (--argc > 0)
  364.             {
  365.               if (bodylink)
  366.                 free (bodylink);
  367.               bodylink = (char*) strdup (argv[a]);
  368.             }
  369.         }
  370.  
  371.       else if (ARGUMENT_IS ("-") || ARGUMENT_IS ("-stdout")) /* stdout output  */
  372.         {
  373.           if (current && current->output_filename)
  374.             {
  375.               free (current->output_filename);
  376.               current->output_filename = NULL;
  377.             }
  378.         }
  379.       else if (ARGUMENT_IS ("-o") || ARGUMENT_IS ("-out")) /* output filename specified  */
  380.         {
  381.           a++;
  382.           if (--argc > 0)  /* must have an extra argument  */
  383.             {
  384.               if (current)
  385.                 {
  386.                   if (current->output_filename)
  387.                     free (current->output_filename);
  388.                   current->output_filename = (char*) strdup (argv[a]);
  389.                 }
  390.             }
  391.         }
  392.       else if (ARGUMENT_IS ("-title"))  /* new title specified  */
  393.         {
  394.           a++;
  395.           if (--argc > 0)  /* must have an extra argument  */
  396.             {
  397.               if (current)
  398.                 {
  399.                   if (current->title_html)
  400.                     free (current->title_html);
  401.                   current->title_html = (unsigned char*) strdup (argv[a]);
  402.                 }
  403.             }
  404.         }
  405.       else
  406.         {
  407.           /* Well, only files (and illegal switches) comes here */
  408.           if (current && current->input_filename)
  409.             {
  410.               /* this entry was allready used, so make a new one  */
  411.               prev = current;
  412.               current =  create_entry ();
  413.               prev->next = current;
  414.             }
  415.           if (current)
  416.             {
  417.               current->input_filename = (char*) strdup (argv[a]);  /* copy that name  */
  418.               /* make some space for the output filename  */
  419.               current->output_filename = (char*) calloc (strlen (current->input_filename) + sizeof (HTML_EXTENSION) + 1, sizeof (char));
  420.               /* calculate the outputname  */
  421.               make_output_filename (current->input_filename, current->output_filename, HTML_EXTENSION);
  422.             }
  423.         }
  424.       a++;
  425.     }  /* while */
  426.  
  427. #ifdef DEBUG
  428.   current = work_list;
  429.  
  430.   while (current)
  431.     {
  432.       fprintf (stderr, "Debug: Filelist = %s %s\n",
  433.           (current->input_filename) ? current->input_filename : "null",
  434.           (current->output_filename) ? current->output_filename : "null" );
  435.       current = current->next;
  436.     }
  437. #endif
  438.  
  439.     /* run through the list and create the files  */
  440.  
  441.     current = work_list;
  442.  
  443.     while (current)
  444.       {
  445.         ret += make_html_file (current->input_filename, current->output_filename, current->title_html);
  446.         current = current->next;
  447.       }
  448.     free_list (work_list);
  449.  
  450.     if (footer_html)
  451.       free (footer_html);
  452.     if (separator_html)
  453.       free (separator_html);
  454.     if (bodybgcolor)
  455.       free (bodybgcolor);
  456.     if (bodytext)
  457.       free (bodytext);
  458.     if (bodylink)
  459.       free (bodylink);
  460.  
  461.     if (pause_required)
  462.       {
  463.         output_error_text ("\nPress Return\n");
  464.         getchar ();
  465.       }
  466.     return (ret > 0) ? 1 : 0;
  467. }
  468.  
  469. /*
  470.  * Parse it and set variables
  471.  */
  472.  
  473.  
  474. void
  475. read_rc_file (char *rc_name)
  476. {
  477.   FILE *fp_rc = fopen_rc_file (rc_name, "r");
  478.  
  479.   if (fp_rc)
  480.     {
  481.       char *buffer = (char*) malloc (RC_LINE_BUFFER+1);
  482.       char *var = (char*) malloc (MAX_VAR_LENGTH+1);
  483.       char *val = (char*) malloc (RC_LINE_BUFFER+1);
  484.  
  485.       if (buffer && var && val)
  486.         {
  487.           /* a rc line looks like "variable = value\n"  */
  488.           while (fgets (buffer, RC_LINE_BUFFER, fp_rc))
  489.             {
  490.               if (buffer[0] != '#')
  491.                 {
  492.                   char *p;                /* pointer to work with  */
  493.                   char *p_equal = NULL;   /* will later pointer at =  */
  494.                   /* remove trailing spaces and nasty codes from end */
  495.                   p = buffer + strlen (buffer) - 1;
  496.                   while ((p >= buffer) && (*p <= ' '))
  497.                     *p-- = '\0';
  498.                   if (buffer[0])  /* still something left?  */
  499.                     {
  500.                       if ((p_equal = strchr (buffer, '=')) > buffer)
  501.                         {
  502.                           /* find variable name  */
  503.                           *p_equal = '\0';    /* split buffer  */
  504.                           p = buffer + strlen (buffer) - 1; /* remove spaces after variable  */
  505.                           while ((p >= buffer) && (*p <= ' '))
  506.                             *p-- = '\0';
  507.                           p = buffer;         /* remove spaces before variable  */
  508.                           while (*p && (*p <= ' '))
  509.                             p++;
  510.                           strncpy (var, p, MAX_VAR_LENGTH);
  511.                           var[MAX_VAR_LENGTH] = '\0';   /* allocated +1, so it's okay  */
  512.  
  513.                           /* get the value  */
  514.                           p = p_equal + 1;
  515.                           while (*p && (*p <= ' '))   /* skip spaces before value */
  516.                             p++;
  517.                           strcpy (val, p);
  518.  
  519.                           if (var[0])         /* allow empty values, but variable must be defined */
  520.                             set_var (var, val);
  521.                         }
  522.  
  523.                     }
  524.                 }
  525.             }
  526.         }
  527.       if (buffer)
  528.         free (buffer);
  529.       if (var)
  530.         free (var);
  531.       if (val)
  532.         free (val);
  533.       fclose (fp_rc);
  534.     }  
  535. }
  536.  
  537.  
  538.  
  539. void
  540. set_var (char *variable, char *value)
  541. {
  542.   register int bool_val;
  543.  
  544.   if (variable && value)
  545.     {
  546.       bool_val = NA;
  547.       if (value[0])
  548.         {
  549.           char **p = yes_strings;
  550.           while (*p)
  551.             { if (!strcmp (value, *p))
  552.                 bool_val = TRUE;
  553.               p++;
  554.             }
  555.           p = no_strings;
  556.           while (*p)
  557.             { if (!strcmp (value, *p))
  558.                 bool_val = FALSE;
  559.               p++;
  560.             }
  561.         }
  562.       /* some trivial tests going on here...  */
  563.       if (!strcmp ("iso", variable) || !strcmp ("iso-8859-1", variable))
  564.         {
  565.           if (bool_val == TRUE)
  566.             method = ISOCHARSET;
  567.           else if (bool_val == FALSE)
  568.             method = ATARICHARSET;
  569.         }
  570.       if (!strcmp ("atari", variable))
  571.         {
  572.           if (bool_val == TRUE)
  573.             method = ATARICHARSET;
  574.           else if (bool_val == FALSE)
  575.             method = ISOCHARSET;
  576.         }
  577.       if (!strcmp ("quiet", variable))
  578.         {
  579.           if (bool_val == TRUE)
  580.             quiet = TRUE;
  581.           else if (bool_val == FALSE)
  582.             quiet = FALSE;
  583.         }
  584.       if (!strcmp ("pause", variable))
  585.         {
  586.           if (bool_val == TRUE)
  587.             pause_required = TRUE;
  588.           else if (bool_val == FALSE)
  589.             pause_required = FALSE;
  590.         }
  591.       if (!strcmp ("crlf", variable))
  592.         {
  593.           if (bool_val == TRUE)
  594.             crlf = TRUE;
  595.           else if (bool_val == FALSE)
  596.             crlf = FALSE;
  597.         }
  598.       if (!strcmp ("notags", variable))
  599.         {
  600.           if (bool_val == TRUE)
  601.             notags = TRUE;
  602.           else if (bool_val == FALSE)
  603.             notags = FALSE;
  604.         }
  605.       if (!strcmp ("nolinks", variable))
  606.         {
  607.           if (bool_val == TRUE)
  608.             nolinks = TRUE;
  609.           else if (bool_val == FALSE)
  610.             nolinks = FALSE;
  611.         }
  612.       if (!strcmp ("nomail", variable))
  613.         {
  614.           if (bool_val == TRUE)
  615.             nomail = TRUE;
  616.           else if (bool_val == FALSE)
  617.             nomail = FALSE;
  618.         }
  619.       if (!strcmp ("nopre", variable))
  620.         {
  621.           if (bool_val == TRUE)
  622.             nopre = TRUE;
  623.           else if (bool_val == FALSE)
  624.             nopre = FALSE;
  625.         }
  626.       if (!strcmp ("nobr", variable))
  627.         {
  628.           if (bool_val == TRUE)
  629.             nobr = TRUE;
  630.           else if (bool_val == FALSE)
  631.             nobr = FALSE;
  632.         }
  633.       if (!strcmp ("nodoctype", variable))
  634.         {
  635.           if (bool_val == TRUE)
  636.             doctype = FALSE;  /* pitfall  */
  637.           else if (bool_val == FALSE)
  638.             doctype = TRUE;
  639.         }
  640.       if (!strcmp ("emailsource", variable))
  641.         {
  642.           if (bool_val == TRUE)
  643.             {
  644.               emailsource = TRUE;
  645.               method = ISOCHARSET;
  646.             }
  647.           else if (bool_val == FALSE)
  648.             emailsource = FALSE;
  649.         }
  650.       if (!strcmp ("footer", variable))
  651.         {
  652.           if (footer_html)
  653.             free (footer_html);
  654.           footer_html = NULL;
  655.           if (value[0])
  656.             footer_html = (char*) strdup (value);
  657.         }
  658.       if (!strcmp ("separator", variable))
  659.         {
  660.           if (separator_html)
  661.             free (separator_html);
  662.           separator_html = NULL;
  663.           if (value[0])
  664.             separator_html = (char*) strdup (value);
  665.         }
  666.       if (!strcmp ("bodybgcolor", variable))
  667.         {
  668.           if (bodybgcolor)
  669.             free (bodybgcolor);
  670.           bodybgcolor = NULL;
  671.           if (value[0])
  672.             bodybgcolor = (char*) strdup (value);
  673.         }
  674.       if (!strcmp ("bodytext", variable))
  675.         {
  676.           if (bodytext)
  677.             free (bodytext);
  678.           bodytext = NULL;
  679.           if (value[0])
  680.             bodytext = (char*) strdup (value);
  681.         }
  682.       if (!strcmp ("bodylink", variable))
  683.         {
  684.           if (bodylink)
  685.             free (bodylink);
  686.           bodylink = NULL;
  687.           if (value[0])
  688.             bodylink = (char*) strdup (value);
  689.         }
  690.     }
  691. }
  692.  
  693.  
  694. /*
  695.  * Search for a2htmlrc file in
  696.  *  1) current working directory
  697.  *  2) HOME (env variable)
  698.  * Looks first after a2htmlrc, then .a2htmlrc
  699.  * Opens the file and returns filepointer
  700.  */
  701.  
  702. FILE *
  703. fopen_rc_file (const char *rc_name, const char *mode)
  704. {
  705.   char *cwd_path = getcwd ( NULL, 0);  /* string is auto. allocated  */
  706.   char *home_path = getenv ("HOME");   /* string not allocated (just a borrow pointer) */
  707.   char *slash_cwd = "/";
  708.   char *slash_home = "/";
  709.   char *a2htmlrc_file = NULL;
  710.   FILE *fp_rc;
  711.     int p_size = 0;
  712.  
  713.   if (cwd_path)
  714.     p_size = (int) strlen (cwd_path);
  715.   if (home_path)  /* Well, just in case it doesn't exist!  */
  716.     p_size = max (p_size, (int) strlen (home_path));
  717.   if (rc_name)
  718.     p_size += (int) strlen (rc_name);
  719.   a2htmlrc_file = (char*) malloc (p_size + 3);
  720.  
  721.   if (rc_name && a2htmlrc_file && (cwd_path || home_path))
  722.     {
  723.       /* first look for a2htmlrc in current working directory  */
  724.       if (cwd_path)
  725.         {
  726.           /* determine slash type  */
  727.           #if defined(ATARI) && !defined(__MINT__)
  728.           /* Using \ in path ?? Not executed in MiNTLib or Linux - could be a BAD THING (TM)*/
  729.           if ((cwd_path[1] == ':') || strchr (cwd_path, '\\'))
  730.              slash_cwd = "\\";
  731.           #endif
  732.           strcpy (a2htmlrc_file, cwd_path);
  733.           strcat (a2htmlrc_file, slash_cwd);
  734.           strcat (a2htmlrc_file, rc_name);
  735.           /* try a2htmlrc  */
  736.           fp_rc = fopen (a2htmlrc_file, mode);
  737.           if (!fp_rc)
  738.             {
  739.               strcpy (a2htmlrc_file, cwd_path);
  740.               strcat (a2htmlrc_file, slash_cwd);
  741.               strcat (a2htmlrc_file, ".");
  742.               strcat (a2htmlrc_file, rc_name);
  743.               /* try .a2htmlrc  */
  744.               fp_rc = fopen (a2htmlrc_file, mode);
  745.             }
  746.         }
  747.       /* then look for it in home directory  */
  748.       if (!fp_rc && home_path)
  749.         {
  750.           /* Hopefully nobody uses \ in fs with / as slash... */
  751.           if ((home_path[1] == ':') || strchr (home_path, '\\'))
  752.             slash_home = "\\";
  753.           strcpy (a2htmlrc_file, home_path);
  754.           strcat (a2htmlrc_file, slash_home);
  755.           strcat (a2htmlrc_file, rc_name);
  756.           /* try a2htmlrc in home */
  757.           fp_rc = fopen (a2htmlrc_file, mode);
  758.           if (!fp_rc)
  759.             {
  760.               strcpy (a2htmlrc_file, home_path);
  761.               strcat (a2htmlrc_file, slash_home);
  762.               strcat (a2htmlrc_file, ".");
  763.               strcat (a2htmlrc_file, rc_name);
  764.               /* try .a2htmlrc in home  */
  765.               fp_rc = fopen (a2htmlrc_file, mode);
  766.             }
  767.         }
  768.     }
  769.   if (a2htmlrc_file)
  770.     free (a2htmlrc_file);
  771.   if (cwd_path)
  772.     free (cwd_path);
  773.   return fp_rc;
  774. }
  775.  
  776.  
  777. struct file_entry
  778. *create_entry (void)
  779. {
  780.   return (struct file_entry*) calloc (1, sizeof (struct file_entry));
  781. }
  782.  
  783.  
  784. void
  785. free_list (struct file_entry* start)
  786. {
  787.   struct file_entry* next;
  788.   struct file_entry* current = start;
  789.  
  790.   while (current)
  791.     {
  792.       next = current->next;
  793.       if (current->input_filename)
  794.         free (current->input_filename);
  795.       if (current->output_filename)
  796.         free (current->output_filename);
  797.       if (current->title_html)
  798.         free (current->title_html);
  799.       free (current);
  800.       current = next;
  801.     }
  802. }
  803.  
  804.  
  805. /*
  806.  * make ex test.txt into test.html, if new_ext is html
  807.  *  special case: if out_filename is present, no filtype substitution is made.
  808.  */
  809.  
  810. void
  811. make_output_filename (const char *in_filename, char *out_filename, const char *new_ext)
  812. {
  813.   if (!in_filename || !out_filename || !*in_filename)
  814.     return;
  815.  
  816.   if (!*out_filename)  /* inputfile, but no outputfile??? */
  817.     {
  818.       register unsigned char *p = NULL;
  819.       register int has_ext = FALSE;
  820.  
  821.       /* use same name as inputfile  */
  822.       strcpy (out_filename, in_filename);
  823.  
  824.       /* replace extension with html if name has a dot in it  */
  825.       if (p = strrchr (out_filename, '.'))
  826.         {
  827.           /* check that the dot is 'after' / or \  (not a dot in path) */
  828.           if ((p > (unsigned char *)strrchr (out_filename, '/')) && (p > (unsigned char *)strrchr (out_filename, '\\')) )
  829.             {
  830.               strcpy (p, new_ext);
  831.               has_ext = TRUE;
  832.             }
  833.         }
  834.       if (!has_ext)
  835.         strcat (out_filename, new_ext); /* no ext, let's give it a html extension  */
  836.     }
  837. }
  838.  
  839.  
  840. void
  841. show_help (int all)
  842. {
  843.  
  844. #ifdef ATARI
  845.   output_error_text (                                                     \
  846.     "a2html "VERSION ", Compiled "__DATE__".\n"                           \
  847.     "Converts a textfile into an iso-8859-1 (7bit) htmlfile\n"            \
  848.     "Written by Tommy Andersen (tommya@post3.tele.dk). Public Domain\n"   \
  849.    );
  850.  
  851.   if (all)
  852.     output_error_text (
  853.       "Usage: a2html [[options] textfile [htmlfile]]\n"                     \
  854.       " Charset options:\n"                                                 \
  855.       "  -iso, -iso-8859-1   Textfile uses iso-8859-1 charset.\n"           \
  856.       "  -atari              Textfile uses Atari charset (default).\n"      \
  857.       " Speciel options:\n"                                                 \
  858.       "  -q, -quiet          Quiet mode - no errortext.\n"                  \
  859.       "  -p, -pause          Wait for a keypress before quit.\n"            \
  860.       "  --help              This help.\n"                                  \
  861.       "  --version           Display a2html version.\n"                     \
  862.       " Input options:\n"                                                   \
  863.       "  <textfile>          Read from textfile.\n"                         \
  864.       "  no <textfile>       Read input from stdin.\n"                      \
  865.       " Input type:\n"                                                      \
  866.       "  -emailsource        Textfile is an email.\n"                       \
  867.       " Output options:\n"                                                  \
  868.       "  -o <htmlfile>, -out <htmlfile>\n"                                  \
  869.       "                      Write to htmlfile.\n"                        \
  870.       "  no <htmlfile>       Write to textfile, filetype changed to html.\n" \
  871.       "                      If input is read from stdin, stdout will be used.\n" \
  872.       "  -, -stdout          Force output to stdout.\n"                     \
  873.       " Html options:\n"                                                    \
  874.       "  -crlf               Lines with CR + LF.\n"                         \
  875.       "  -nodoctype          No doctype in htmlfile.\n"                     \
  876.       "  -title <string>     Use string as title in htmlfile.\n"            \
  877.       "  -bodybgcolor <color>\n"                                            \
  878.       "                      Change background color.\n"                    \
  879.       "  -bodytext <color>   Change text color.\n"                          \
  880.       "  -bodylink <color>   Change link color.\n"                          \
  881.       "  -notags             No <header><title><body> tags in htmlfile.\n"  \
  882.       "  -nopre              No <pre> tags in output - <br> are generated.\n"\
  883.       "  -nobr               No <br> if -nopre is used.\n"                  \
  884.       "  -footer <string>    Use string as footer.\n"                       \
  885.       "  -separator <string> Use string as separator (-emailsource).\n"     \
  886.       " Url options:\n"                                                     \
  887.       "  -nolinks            Don't make href in htmlfile.\n"                \
  888.       "  -nomail             Don't make mailto in htmlfile.\n"              \
  889.       );
  890. #else
  891.   output_error_text (                                                     \
  892.     "a2html "VERSION ", Compiled "__DATE__".\n"                           \
  893.     "Converts a textfile into an iso-8859-1 (7bit) htmlfile\n"            \
  894.     "Written by Tommy Andersen (tommya@post3.tele.dk) Public Domain\n"    \
  895.    );
  896.  
  897.   if (all)
  898.     output_error_text (
  899.       "Usage: a2html [[options] textfile [htmlfile]]\n"                     \
  900.       " Charset options:\n"                                                 \
  901.       "  -iso, -iso-8859-1   Textfile uses iso-8859-1 charset (default).\n" \
  902.       "  -atari              Textfile uses Atari charset.\n"                \
  903.       " Speciel options:\n"                                                 \
  904.       "  -q, -quiet          Quiet mode - no errortext.\n"                  \
  905.       "  -p, -pause          Wait for a keypress before quit.\n"            \
  906.       "  --help              This help.\n"                                  \
  907.       "  --version           Display a2html version.\n"                     \
  908.       " Input options:\n"                                                   \
  909.       "  <textfile>          Read from textfile.\n"                         \
  910.       "  no <textfile>       Read input from stdin.\n"                      \
  911.       " Input type:\n"                                                      \
  912.       "  -emailsource        Textfile is an email.\n"                       \
  913.       " Output options:\n"                                                  \
  914.       "  -o <htmlfile>, -out <htmlfile>\n"                                  \
  915.       "                      Write to htmlfile.\n"                          \
  916.       "  no <htmlfile>       Write to textfile, filetype changed to html.\n" \
  917.       "                      If input is read from stdin, stdout will be used.\n" \
  918.       "  -, -stdout          Force output to stdout.\n"                     \
  919.       " Html options:\n"                                                    \
  920.       "  -crlf               Lines with CR + LF.\n"                         \
  921.       "  -nodoctype          No doctype in htmlfile.\n"                     \
  922.       "  -title <string>     Use string as title in htmlfile.\n"            \
  923.       "  -bodybgcolor <color>\n"                                            \
  924.       "                      Change background color.\n"                    \
  925.       "  -bodytext <color>   Change text color.\n"                          \
  926.       "  -bodylink <color>   Change link color.\n"                          \
  927.       "  -notags             No <header><title><body> tags in htmlfile.\n"  \
  928.       "  -nopre              No <pre> tags in output - <br> are generated.\n"\
  929.       "  -nobr               No <br> if -nopre is used.\n"                  \
  930.       "  -footer <string>    Use string as footer.\n"                       \
  931.       "  -separator <string> Use string as separator (-emailsource).\n"     \
  932.       " Url options:\n"                                                     \
  933.       "  -nolinks            Don't make href in htmlfile.\n"                \
  934.       "  -nomail             Don't make mailto in htmlfile.\n"              \
  935.       );
  936. #endif
  937. }
  938.  
  939.  
  940.  
  941. int
  942. make_html_file (char *input_filename, char *output_filename, const unsigned char *title)
  943. {
  944.   register int c;
  945.   unsigned char word[WORD_LENGTH+1];
  946.   register FILE *inhandle = NULL;
  947.   register FILE *outhandle = NULL;
  948.  
  949.   /* check for same input file as outputfile  */
  950.  
  951.   if (input_filename && output_filename)
  952.     if (!strcmp (input_filename, output_filename))
  953.       {
  954.         output_error_text ("Error: inputfile same as outputfile!\n");
  955.         return 1;
  956.       }
  957.  
  958.   if (input_filename)
  959.     inhandle = fopen (input_filename, "rb");
  960.   else
  961.     inhandle = stdin;
  962.  
  963.  
  964.   if (inhandle)  /* don't create files, if inputfile couldn't be opened  */
  965.     {
  966.       if (output_filename)
  967.         outhandle = fopen (output_filename, "wb");
  968.       else
  969.         outhandle = stdout;
  970.     }
  971.  
  972.   if (inhandle && outhandle)
  973.     {
  974.       /* Write Html headers */
  975.  
  976.       if (!notags)
  977.         {
  978.           char *some_text = (char*) malloc (1000);
  979.  
  980.           if (doctype)
  981.             output_string (FALSE, header_doctype, outhandle);
  982.  
  983.           output_string (FALSE, header_tags1, outhandle);
  984.  
  985.           if (title)
  986.             output_parse_string (FALSE, title, outhandle);
  987.           else if (input_filename && *input_filename)
  988.             output_parse_string (FALSE, find_filename (input_filename), outhandle);
  989.           else
  990.             output_parse_string (FALSE, "No title", outhandle);
  991.  
  992.           output_string (FALSE, header_tags2, outhandle);
  993.  
  994.           /* make a body  */
  995.           if (some_text)
  996.             {
  997.               /* bgcolor */
  998.               sprintf (some_text, "<body bgcolor=\"%s\"", (bodybgcolor) ? bodybgcolor : "White" );
  999.               output_string (FALSE, some_text, outhandle);
  1000.  
  1001.               sprintf (some_text, " text=\"%s\"", (bodytext) ? bodytext : "Black" );
  1002.               output_string (FALSE, some_text, outhandle);
  1003.  
  1004.               sprintf (some_text, " link=\"%s\"", (bodylink) ? bodylink : "Blue" );
  1005.               output_string (FALSE, some_text, outhandle);
  1006.  
  1007.               output_string (FALSE, ">\n", outhandle);
  1008.  
  1009.               free (some_text);
  1010.             }
  1011.           else
  1012.             {
  1013.               output_string (FALSE, "<body bgcolor=\"White\" text=\"Black\" link=\"Blue\">\n", outhandle);
  1014.             }
  1015.         }
  1016.  
  1017.  
  1018.       /* Speciel input file  */
  1019.       /* Emails should never use Atari charset, so we assumes iso-8859-1 is used  */
  1020.       /* Quoted-printable and mime encoded emails are _not_ decoded  */
  1021.       /* The complete header is inserted into a comment (outside the <pre> tags ) */
  1022.       /* Valid fields are 'saved' and later output'd  */
  1023.  
  1024.       if (emailsource)
  1025.         {
  1026.           int email_header_mode = TRUE;
  1027.           int line_must_out = FALSE;
  1028.           unsigned char *emh_line = (unsigned char*) malloc (2000+1); /* many $ mailers breaks the rules  */
  1029.           unsigned char *p;
  1030.           struct emh_text_entry *current, *emh_work_list;
  1031.  
  1032.           current = emh_work_list = (struct emh_text_entry*) calloc (1, sizeof (struct emh_text_entry));
  1033.  
  1034.           if (emh_line && emh_work_list)
  1035.             {
  1036.               output_string (FALSE, "<!--  Complete header follows -->\n", outhandle);
  1037.           
  1038.               while (!feof (inhandle) && email_header_mode)
  1039.                 {
  1040.                   emh_line[0] = '\0';
  1041.                   if (fgets (emh_line, 2000, inhandle))
  1042.                     {
  1043.                       if (emh_line[0] == '\r' || emh_line[0] == '\n')
  1044.                         {
  1045.                           email_header_mode = FALSE;  /* marker reached  */
  1046.                           line_must_out = FALSE;
  1047.                         }
  1048.                       else if (emh_line[0] > ' ')
  1049.                         {
  1050.                           int i = 0;
  1051.                           line_must_out = FALSE;
  1052.  
  1053.                           /* check for a valid field to be saved  */
  1054.                           while (!line_must_out && show_emh_field[i] )
  1055.                             {
  1056.                               if (!strncasecmp (emh_line, show_emh_field[i], strlen (show_emh_field[i])))
  1057.                                 {
  1058.                                   line_must_out = TRUE;
  1059.                                 }                                  
  1060.                               i++;
  1061.                             }
  1062.                         }
  1063.  
  1064.                       /* Save the field  */
  1065.                       if (line_must_out && current)
  1066.                         {
  1067.                           if (!current->text)
  1068.                             current->text = (unsigned char*) strdup (emh_line);
  1069.  
  1070.                           if (current->next = (struct emh_text_entry*) calloc (1, sizeof (struct emh_text_entry)))
  1071.                             current = current->next;
  1072.                         }
  1073.  
  1074.                       output_string (FALSE, "<!-- ", outhandle);
  1075.                       p = emh_line;    /* remove unwanted characters from comments  */
  1076.                       while (*p)
  1077.                         {
  1078.                           if (*p < ' ')
  1079.                             *p = ' ';
  1080.                            p++;
  1081.                         }
  1082.                       output_string (FALSE, emh_line, outhandle);
  1083.                       output_string (FALSE, " -->\n", outhandle);
  1084.                     }  /* if fgets  */
  1085.                 }  /* while  */
  1086.               output_string (FALSE, "<!--  End of header -->\n", outhandle);
  1087.  
  1088.               if (!nopre)
  1089.                  output_string (FALSE, pre_start_tag, outhandle);
  1090.  
  1091.               /* output the fields to be displayed  */
  1092.               current = emh_work_list;
  1093.               while (current)
  1094.                 {
  1095.                   /* lets parse and output fields  */
  1096.                   if (current->text)
  1097.                     {
  1098.                       register unsigned char *p = current->text;
  1099.  
  1100.                       while (*p)
  1101.                         {
  1102.                           c = *p++;
  1103.                           if ( c <= ' ' || c == '<' || c == '>' || c == '\"' || c=='(' || c == ';' || c=='\'' || c==')' || c=='/')
  1104.                           output_parse_char (TRUE, c, outhandle);
  1105.                           else
  1106.                             {
  1107.                               /* build a word  */
  1108.                               int i = 0;
  1109.                               word[i++] = (unsigned char) c;
  1110.                               while (*p && c > ' ' && c!= '<' && c!= '>' && c!='\"')
  1111.                                 {
  1112.                                   c = *p++;
  1113.                                   if ( c > ' ' && c!= '<' && c!= '>' && c != '\"')
  1114.                                     if (i < WORD_LENGTH)
  1115.                                       word[i++] = (unsigned char) c;
  1116.                                 }
  1117.                               word[i] = '\0';
  1118.                               output_word (TRUE, word, outhandle);
  1119.                               output_parse_char (TRUE, c, outhandle);
  1120.                             }
  1121.                         }
  1122.                     }
  1123.                   current = current->next;
  1124.                 }
  1125.               if (!nopre)
  1126.                  output_string (FALSE, pre_end_tag, outhandle);
  1127.               
  1128.               if (separator_html)
  1129.                 {
  1130.                   output_string (FALSE, separator_html, outhandle);
  1131.                   output_string (FALSE, "\n", outhandle);
  1132.                 }
  1133.               else
  1134.                 if (nopre)
  1135.                   output_string (FALSE, "<br>\n", outhandle);
  1136.  
  1137.               /* Cleanup the malloc'ed mess  */
  1138.               free (emh_line);
  1139.               current = emh_work_list;
  1140.               while (current)
  1141.                 {
  1142.                   register struct emh_text_entry *temp;
  1143.  
  1144.                   if (current->text)
  1145.                     free (current->text);
  1146.                   temp = current->next;
  1147.                   free (current);
  1148.                   current = temp;
  1149.                 }
  1150.             } /* if  */
  1151.         }
  1152.       /* End of speciel input file  */
  1153.  
  1154.  
  1155.       /* And the text (body) */
  1156.  
  1157.       if (!nopre)
  1158.         output_string (FALSE, pre_start_tag, outhandle);
  1159.  
  1160.       word[0] = '\0';
  1161.  
  1162.       while (!feof (inhandle))
  1163.         {
  1164.           c = fgetc (inhandle);
  1165.           if ( c >= 0)  /* c will be <0 if eof reached  */
  1166.             {
  1167.               if ( c <= ' ' || c == '<' || c == '>' || c == '\"' || c=='(' || c == ';' || c=='\'' || c==')' || c=='/')
  1168.                 output_parse_char (TRUE, c, outhandle);  /* not the beginning of a word, so just output it  */
  1169.               else
  1170.                 {
  1171.                   /* build a word  */
  1172.                   int i = 0;
  1173.                   word[i++] = (unsigned char) c;
  1174.                   while (!feof (inhandle) && c > ' ' && c!= '<' && c!= '>' && c!='\"')
  1175.                     {
  1176.                       c = fgetc (inhandle);
  1177.                       if ( c > ' ' && c!= '<' && c!= '>' && c != '\"')
  1178.                         if (i < WORD_LENGTH)
  1179.                           word[i++] = (unsigned char) c;
  1180.                     }
  1181.                   word[i] = '\0';
  1182.                   output_word (TRUE, word, outhandle);
  1183.                   if (!feof (inhandle))
  1184.                     output_parse_char (TRUE, c, outhandle);
  1185.                 }
  1186.             }
  1187.         }
  1188.       if (inhandle != stdin)  /* clean close  */
  1189.         fclose (inhandle);
  1190.  
  1191.       /* Now write the end tags */
  1192.       output_string (FALSE, "\n", outhandle);  /* ensure that the end tags are starting on a new line  */
  1193.       if (!nopre)
  1194.         output_string (FALSE, pre_end_tag, outhandle);
  1195.  
  1196.       if (footer_html)
  1197.         {  
  1198.           output_string (FALSE, footer_html, outhandle);
  1199.           output_string (FALSE, "\n", outhandle);  /* ensures that the next tags are starting on a new line  */
  1200.         }
  1201.  
  1202.       if (!notags)
  1203.         output_string (FALSE, bottom_tags, outhandle);
  1204.  
  1205.       if (outhandle != stdout)
  1206.         fclose (outhandle);    /* well, should check the return value here */
  1207.  
  1208.     }
  1209.    else
  1210.     {
  1211.       char *sometext = (char*) malloc (1000);  /* should be enough  */
  1212.       if (sometext)
  1213.         {
  1214.           sprintf (sometext, "Can not open inputfile [%s] or outputfile [%s]\n",
  1215.             (input_filename ? input_filename : "stdin"), (output_filename ? output_filename : "stdout"));
  1216.           output_error_text (sometext);
  1217.           free (sometext);
  1218.         }
  1219.       return 1;
  1220.     }
  1221.   return 0;
  1222. }
  1223.  
  1224.  
  1225. /*
  1226.  * Print some errortext to stderr
  1227.  * Errortext will no be printed if in quiet mode
  1228.  */
  1229. void
  1230. output_error_text (char *string)
  1231. {
  1232.   if (!quiet)
  1233.     fprintf (stderr, string);
  1234. }
  1235.  
  1236.  
  1237. /*
  1238.  * Return the address of first letter in the filename
  1239.  * argument string is a path+filename
  1240.  *  ex: d:\directory\filename.ext
  1241.  *      ^string      ^return
  1242.  */
  1243. char *
  1244. find_filename (char *string)
  1245. {
  1246.   register char *p=string;
  1247.  
  1248.   if (string)
  1249.     {
  1250.       p += strlen (string);
  1251.       while (p>string && *(p-1) !='\\' && *(p-1) !=':' && *(p-1)!='/' )
  1252.         p--;
  1253.     }
  1254.   return p;
  1255. }
  1256.  
  1257.  
  1258. /*
  1259.  * Outputs a char to the html file
  1260.  * No charset parsing
  1261.  * If the char is a LF (ascii 10), then it will finish the line.
  1262.  */
  1263. void
  1264. output_char (int allow_br, int c, FILE *handle)
  1265. {
  1266.   if (c == 10)
  1267.     {
  1268.       if (nopre && !nobr && allow_br)     /* end of line and no pre -> we make the line ends with <br>  */
  1269.         output_string (FALSE, "<br>", handle);  /* note! recursive! Never \n in this one!!  */
  1270.       if (crlf)
  1271.         fputc (13, handle);
  1272.     }
  1273.   fputc (c, handle);
  1274. }
  1275.  
  1276.  
  1277. /*
  1278.  * Outputs a string to the html file
  1279.  * No charset parsing
  1280.  */
  1281. void
  1282. output_string (int allow_br, const char *s, FILE *handle)
  1283. {
  1284.   if (s)
  1285.     while (*s)
  1286.       output_char (allow_br, *s++, handle);
  1287. }
  1288.  
  1289.  
  1290. /*
  1291.  * Outputs a char to the html file
  1292.  * Char will be charset parsed
  1293.  */
  1294. void
  1295. output_parse_char (int allow_br, unsigned int c, FILE *handle)
  1296. {
  1297.   if (method == ATARICHARSET)
  1298.     c = convertAtariToIso88591[ c & 0xff ];
  1299.   output_string (allow_br, convertIso88591ToHtml[ c & 0xff ], handle);
  1300. }
  1301.  
  1302.  
  1303. /*
  1304.  * Outputs a string to the html file
  1305.  * String will be charset parsed
  1306.  */
  1307. void
  1308. output_parse_string (int allow_br, const char *s, FILE *handle)
  1309. {
  1310.   register unsigned int c;
  1311.  
  1312.   if (s)
  1313.     while (*s)
  1314.       {
  1315.         c = (unsigned int) *s++;
  1316.         if (method == ATARICHARSET)
  1317.           c = convertAtariToIso88591[ c & 0xff ];
  1318.         output_string (allow_br, convertIso88591ToHtml[ c & 0xff], handle);
  1319.       }
  1320. }
  1321.  
  1322. /*
  1323.  * check word for any url style in it and make a link.
  1324.  * outputs the word too.
  1325.  * Not 100% fool-proof, but shouldn't miss too many url's.
  1326.  */
  1327. void
  1328. output_word (int allow_br, const unsigned char *word, FILE *handle)
  1329. {
  1330.   unsigned char *url_checker = NULL;
  1331.   unsigned char *email_checker = NULL;
  1332.  
  1333.   if ( !nolinks && (url_checker = strchr (word, ':')))
  1334.     {
  1335.       /* examples: (http://localhost/) "ftp://sunsite.auc.dk". */
  1336.       unsigned char url_host[WORD_LENGTH+1];
  1337.       int url_ok = FALSE;
  1338.       int url_index = 0;
  1339.       int pre_chars = (int)(url_checker - word);
  1340.  
  1341.       /* check for <url:http://...> type  */
  1342.       /* if so, then move the url_checker pointer to the second :  */
  1343.       if (pre_chars >= strlen ("url") )
  1344.         if (!strncasecmp (url_checker-(long)strlen ("url"), "url", strlen ("url") ))
  1345.           {
  1346.             unsigned char *p = url_checker;
  1347.             url_checker = strchr (url_checker+1, ':');  /* find next :  */
  1348.             pre_chars = (int) (url_checker - p - 1);  /* recalculate it  */
  1349.           }
  1350.       /* look for a valid urltype  */
  1351.       while ( url_types[url_index] && !url_ok && url_checker)  /* an url_type, not found and :  */
  1352.         {
  1353.           if (pre_chars == strlen (url_types[url_index]) )  /* enough (exact) chars in word before :  */
  1354.             {
  1355.               if (!strncasecmp (url_checker-(long)strlen (url_types[url_index]), url_types[url_index], strlen (url_types[url_index]) ))
  1356.                 {
  1357.                   /* found a match */
  1358.                   register unsigned char *p = NULL;
  1359.                   int count = (int)(url_checker - word +1);  /* chars before the url */
  1360.                   strcpy (url_host, url_checker+1);
  1361.                   /* now... remove any " */
  1362.                   if (*url_host)
  1363.                     if (p = strchr (url_host, '\"'))
  1364.                       *p = '\0';
  1365.                   /* remove any <  - these can't be in the word, but the " removing
  1366.                    * thing above could dig something nasty out of the url.
  1367.                    */
  1368.                   if (*url_host)
  1369.                     if (p = strchr (url_host, '<'))
  1370.                       *p = '\0';
  1371.                   /* remove any > */
  1372.                   if (*url_host)
  1373.                     if (p = strchr (url_host, '>'))
  1374.                       *p = '\0';
  1375.                   /* remove trailing ,.;\?! */
  1376.                   if (*url_host)
  1377.                     {
  1378.                       p = url_host + strlen (url_host) - 1;
  1379.                       while ((p >= url_host) && strchr (",.;:!?\\", (int)*p))  /* protect me  */
  1380.                         *p-- = '\0';
  1381.                     }
  1382.                   /* count () and remove unbalanced ) in url */
  1383.                   if (*url_host)  /* still something left?  */
  1384.                     {
  1385.                       int par_start = 0;
  1386.                       int par_end = 0;
  1387.                       unsigned char *p2 = NULL;
  1388.                       p = url_host;
  1389.                       while (p = strchr (p, '('))
  1390.                         {
  1391.                           par_start++;
  1392.                           p++;
  1393.                         }
  1394.                       p = url_host;
  1395.                       while (p = strchr (p, ')'))
  1396.                         {
  1397.                           par_end++;
  1398.                           p++;
  1399.                         }
  1400.                       while (par_end-- > par_start)  /* remove em */
  1401.                         if (p2 = strrchr (url_host, ')'))
  1402.                           *p2 = '\0';
  1403.                     }
  1404.                   /* make a small validator */
  1405.                   if (*url_host)
  1406.                     {
  1407.                       p = url_host;
  1408.                       /* skip /  */
  1409.                       while (*p == '/')
  1410.                         p++;
  1411.                       if (*p)
  1412.                         {
  1413.                           int trailing_chars = (strlen (url_checker+1) - strlen (url_host)) > 0 ? TRUE : FALSE;
  1414.                           url_ok = TRUE;  /* yup, let's make a link  */
  1415.                           /* a little string copy and manipulation  */
  1416.  
  1417.                           output_string (allow_br, "<a href=\"", handle);
  1418.                           output_string (allow_br, url_types[url_index], handle);
  1419.                           output_char (allow_br, ':', handle);
  1420.                           output_string (allow_br, url_host, handle);
  1421.                           output_string (allow_br, "\">", handle);
  1422.                           if (trailing_chars)
  1423.                             {
  1424.                               int url_length = (int) strlen (url_host);
  1425.                               /* find what are going to be hightlighted  */
  1426.                               strcpy (url_host, word);  /* copy all - using the array */
  1427.                               url_host[count + url_length] = '\0'; /* zero it  */
  1428.                               /* highlight stuff  */
  1429.                               output_parse_string (allow_br, url_host, handle);
  1430.                               /* and what's left are not going to be highlighted  */
  1431.                               output_string (allow_br, "</a>", handle);
  1432.                               /* let's output that  */
  1433.                               output_parse_string (allow_br, &word[count + url_length], handle);
  1434.                             }
  1435.                           else
  1436.                             {
  1437.                               output_parse_string (allow_br, word, handle);
  1438.                               output_string (allow_br, "</a>", handle);
  1439.                             }
  1440.                         }
  1441.                     }
  1442.                 }
  1443.             }
  1444.           url_index++;
  1445.         }
  1446.       if (!url_ok)
  1447.         {
  1448.           /* not a valid url  */
  1449.           output_parse_string (allow_br, word, handle);
  1450.         }
  1451.     }
  1452.   else if (!nomail && (email_checker = strchr (word, '@')))
  1453.     {
  1454.       /* or perhaps a email address
  1455.        * examples <tommya@post3.tele.dk>  (me@here) him@there "user@anywhere"
  1456.        */
  1457.       int email_ok = FALSE;
  1458.       unsigned char email_address[WORD_LENGTH+1];
  1459.       register unsigned char *p = (unsigned char *) word;
  1460.  
  1461.       strcpy (email_address, p);
  1462.       p = email_address;
  1463.       if (*p == '@')  /* start with a @ ??  */
  1464.         *p = '\0';    /* surely an illegal emailaddress  */
  1465.  
  1466.       while (*p && !strchr (">\"\'\\);", (int) *p))  /* look for ">');\ that ends the emailaddress  */
  1467.         p++;
  1468.       *p = '\0';  /* found the end of the emailaddress  */
  1469.  
  1470.       /* remove _trailing_ dots, commas, !, ?. Still legal: user@host?subject */
  1471.       if (*email_address)
  1472.         {
  1473.           p = email_address + strlen (email_address) - 1;
  1474.           while ((p >= email_address) && strchr (",.?!:", (int)*p))   /* protect me  */
  1475.             *p-- = '\0';
  1476.         }
  1477.       email_checker = strchr (email_address, '@');    /* better check again for @  */
  1478.       if (email_checker && strlen (email_checker+1) && !strchr (email_checker+1, '@'))  /* a host, length and no double @ ??  */
  1479.         {
  1480.           /* okay, lets make a mailto  */
  1481.           email_ok = TRUE;
  1482.           output_string (allow_br, "<a href=\"mailto:", handle);
  1483.           output_string (allow_br, email_address, handle);
  1484.           output_string (allow_br, "\">", handle);
  1485.           if (strlen (email_address) != strlen (word))
  1486.             {
  1487.               output_parse_string (allow_br, email_address, handle);
  1488.               output_string (allow_br, "</a>", handle);
  1489.               /* not highlighted stuff  */
  1490.               output_parse_string (allow_br, &word[(int)strlen (email_address)], handle);
  1491.             }
  1492.           else  /* no trailing things  */
  1493.             {
  1494.               output_parse_string (allow_br, word, handle);
  1495.               output_string (allow_br, "</a>", handle);
  1496.             }
  1497.         }
  1498.         if (!email_ok)
  1499.           {
  1500.             /* not a valid url  */
  1501.             output_parse_string (allow_br, word, handle);
  1502.           }
  1503.     }
  1504.   else  /* nop, just parse the string */
  1505.     output_parse_string (allow_br, word, handle);
  1506. }
  1507.  
  1508.